/* $RCSFile: ADNEncryptedLicenseProvider.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/ADNCRM.ServerControls/LicenceControls/ADNEncryptedLicenseProvider.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:30  christian.surieux
 *   Added Log to All cs files
 */

// ADNEncryptedLicenseProvider.cs
// Server Controls and Components
//

using System;
using System.Diagnostics;
using System.Configuration;
using System.Web;
using System.Web.Configuration;
using System.IO;
using System.Data;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Security.Cryptography;

namespace ADNCRM.ServerControls 
{

	public class ADNEncryptedLicenseProvider : ADNBaseLicenseProvider 
	{

		// This is a 64 bit key generated from the string
		// 5FB270E5
		private static readonly byte[] encryptionKeyBytes =
			new byte[] { 0x35, 0x46, 0x42, 0x32, 0x37, 0x30, 0x45, 0x35 };

		private	Dictionary<string,string> _PinDic 	=	new Dictionary<string,string>();
		private	string	_Company			=	string.Empty;

		/// <summary>
        /// Get the pin code from settings, works for winforms or asp taking app.exe.config or web.config
        /// needs a section named with the productName with key LicensePIN
        /// </summary>
        public	string	getCustPin(string productName)
		{
			string custPin			=	string.Empty;
            if ( !_PinDic.ContainsKey(productName) )
            {
                try
                {
                    Company comp = null;
                    //const string strLicKey = "LicensePIN";
                    if (HttpContext.Current == null)
                    {
                        // search for section
                        comp = Company.GetConfig();
                    }
                    else
                    {
                        comp = Company.GetConfig();
                    }
                    if (comp != null)
                    {
                        foreach (LicenseKey lic in comp.Licenses)
                        {
                            if (lic.Product == productName)
                            {
                                custPin = lic.LicensePIN;
                                break;
                            }
                        }
                    }
                    if ( LicenseTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider getCustPin: '{0}'", custPin),LicenseTraceSwitch.Sw.Info);
					if ( !string.IsNullOrEmpty(custPin) )
						_PinDic.Add(productName,custPin);
                }
                catch (Exception ex)
                {
                    custPin = string.Empty;
                    if ( LicenseTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNEncryptedLicenseProvider getCustPin ex: {0}", ex),LicenseTraceSwitch.Sw.Info);
                }
            }
			else custPin =_PinDic[productName];
            return custPin;
        }

        /// <summary>
        /// Get the license company name from settings, works for winforms or asp taking app.exe.config or web.config
        /// using the Name attribute from the Company section in License section group
        /// </summary>
        protected string CompanyName
        {
            get
            {
                if (string.IsNullOrEmpty(_Company))
                {
                    try
                    {
                        Company comp = null;
                        if (HttpContext.Current == null)
                        {
                            // search for section
                            comp = Company.GetConfig();
                        }
                        else
                        {
                            comp = Company.GetConfig();
                        }
                        if (comp != null)
                        {
                            _Company    =   comp.Name;
                            if ( LicenseTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider CompanyName: '{0}'", _Company),LicenseTraceSwitch.Sw.Info);
                        }
                    }
                    catch (Exception ex)
                    {
                        _Company = string.Empty;
                        if ( LicenseTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider CompanyName ex: {0}", ex),LicenseTraceSwitch.Sw.Info);
                    }
                }
                return _Company;
            }
        }


		protected override ADNBaseLicense CreateLicense(Type type, string key) 
		{
			return new ADNEncryptedLicense(type, key);
		}

		/// <summary>
        /// Compares the license file hidden data with the license file entrered with InstallLicense
        /// </summary>
        protected override bool ValidateLicense(ADNBaseLicense license, out string errorMessage)
        {
            errorMessage = null;

            if (!license.IsValid)
            {
                string fmt = "The License for {0} has expired.";
                //CultureInfo ci = Thread.CurrentThread.CurrentUICulture;

                try
                {
                    try
                    {
                        string str      =   AssemblyResourceManager.GetString("ADNCRM_EXPIRED_LIC_FMT");
                        if (!string.IsNullOrEmpty(str))
                            fmt         =   str;
                    }
                    catch (Exception ex)
                    {
                        if ( LicenseTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNEncryptedLicenseProvider Getting format string, Ex: {0}", ex),LicenseTraceSwitch.Sw.Info);
                    }
                    errorMessage        =   string.Format(fmt, license.LicensedType.Name);
                }
                catch (Exception ex)
                {
                    if ( LicenseTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]ADNEncryptedLicenseProvider ValidateLicense ex: {0}", ex),LicenseTraceSwitch.Sw.Info);
                }
                return false;
            }
            return true;
        }

		/// <summary>
		/// Compares the license file hidden data with the license file entrered with InstallLicense
		/// </summary>
        protected override bool ValidateLicenseData(Type type, string licenseData) 
		{
			string[] parts			=	licenseData.Split(new char[]{';'},StringSplitOptions.RemoveEmptyEntries);
			string assemblyPart		=	type.Assembly.GetName().Name;
			string versionPart		=	type.Assembly.GetName().Version.ToString();


            if ( LicenseTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData Type: {0}, assemblyPart: {1}, versionPart: {2}, name: {3}, assembly: {4}, parts.Length: {5}.", 
                    new object[] { type.Name, assemblyPart, versionPart, parts[1], parts[2],parts.Length }),LicenseTraceSwitch.Sw.Info);

			//if ( !_IsInitialized && _IsOk )
            //    Initialize(type.Name);

            // check each component of the crypted license
            while ( parts.Length >= 10 ) 
			{
                // License name
                if (parts[1] != type.Name)
                {
                    if ( LicenseTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData ( parts[1]:{0} ) != ( type.Name:{1} )", new object[] { parts[1], type.Name }),LicenseTraceSwitch.Sw.Info);
                    break;
                }
                // assembly containing the license
                if (parts[2] != assemblyPart)
                {
                    if ( LicenseTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData ( parts[2]:{0} ) != ( assemblyPart:{1} )", new object[] { parts[2], assemblyPart }),LicenseTraceSwitch.Sw.Info);
                    break;
                }
                // type of license: Demo, full, CRM limited , see ADNLicense
				if ( parts[4].IndexOf("Demo") == -1 )
				{
                    if ( LicenseTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData ( parts[4]:{0} ) != 'Demo' )", parts[4]),LicenseTraceSwitch.Sw.Info);
                    // company, if any it is a corporate license
                    if ( parts[7] != "Any")
					{
                        if ( LicenseTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData ( parts[7]:{0} ) != 'Any' )", parts[7]),LicenseTraceSwitch.Sw.Info);
						// still not there, exit
                        if (string.IsNullOrEmpty(CompanyName))
                        {
                            if ( LicenseTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( "[V]ADNEncryptedLicenseProvider ValidateLicenseData LicencedCompanyName is Null",LicenseTraceSwitch.Sw.Info);
                            break;
                        }
                        if (CompanyName != parts[7])
                        {
                            if ( LicenseTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData ( parts[7]:{0} ) != ( _Company:{1} )", new object[] { parts[7], CompanyName }),LicenseTraceSwitch.Sw.Info);
                            break;
                        }
					}

				}
                // read the Pin associated with this licensed product
				// NB: we still check for pin code with demo licences so the user needs to enter it on the install proc
                string custPin			=	getCustPin(type.Name);
                if ( string.IsNullOrEmpty(custPin) )
                {
                    if ( LicenseTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]ADNEncryptedLicenseProvider ValidateLicenseData _CustPin is Null",LicenseTraceSwitch.Sw.Info);
                    break;
                }
                if ( custPin != parts[8] )
                {
                    if ( LicenseTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]ADNEncryptedLicenseProvider ValidateLicenseData ( parts[8]) != ( _CustPin:{0} )", custPin),LicenseTraceSwitch.Sw.Info);
                    break;
                }
                // if we get there it's Ok
			    return true;
			}
		    return false;
		}
		
		protected override Stream GetLicenseDataStream(Type type) 
		{
			Stream baseStream = base.GetLicenseDataStream(type);

			if (baseStream == null) 
			{
				return null;
			}

			DESCryptoServiceProvider des	=	new DESCryptoServiceProvider();
			des.Key							=	encryptionKeyBytes;
			des.IV							=	encryptionKeyBytes;

			ICryptoTransform desDecryptor	=	des.CreateDecryptor();
			return new CryptoStream(baseStream, desDecryptor, CryptoStreamMode.Read);
		}
	}
}
